import * as THREE from 'three';
// import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js';
import { FlyControls } from 'three/examples/jsm/controls/FlyControls.js';
import { TWEEN } from 'three/examples/jsm/libs/tween.module.min';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { GLTFExporter } from 'three/examples/jsm/exporters/GLTFExporter';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
import Stats from 'three/examples/jsm/libs/stats.module.js';
import { GUI } from 'three/examples/jsm/libs/dat.gui.module.js';
import { baseUrl } from '../../js/base.js';
import { OrbitControls } from './no_pack_js/OrbitControls';

import '../../css/base.css';

let body = document.body,
  canvas = document.getElementById('canvas');
let renderer,
  scene,
  camera; // 场景、相机、渲染器

let stats, // 性能检测器
  orbitControls, // 控制器
  flyControls,
  clock = new THREE.Clock();

// 建筑物楼层每层数据
let buildingParams = window.buildingParams = {
  0: {
    floorNumber: 0,
    floorH: 6,
    position: new THREE.Vector3(),
    object: null,
    userData: null
  }
};

let buildingGroup = new THREE.Group();
let mouse = new THREE.Vector2(), // 指针位置
  point = null, // 指针点击位置
  mouseClick = new THREE.Vector2(); // 指针点击位置
let raycasterObject = []; // 选中的楼层对象
let raycaster = new THREE.Raycaster(); // 射线

let faceGroup = new THREE.Group(),  // 画面的组
  face,
  lineGroup = new THREE.Group(), // 画线的组
  line, // 画玩的线对象
  mousePoint; // 标点是跟随鼠标的点
let pointsList = []; // 画点、线、面临时存放的点数据

// gui 操作参数
const guiParams = window.guiParams = {
  open: true,
  drawPoint: false,
  drawLine: false,
  drawFace: false,
  setUpFloor: false,
  selectFloorActive: -1, // 选中的楼层
  selectFloor: [-1, 0, 1, 2, 3],
};

// 单层楼层点、线、面的数据
let floorParams = window.floorParams = {
  // 单层楼点数据
  points: [{
    'name': '0',
    'floorNumber': 0,
    'point': {
      'x': 59.81369177218892,
      'y': 1,
      'z': -1.9863392807017988
    }
  }, {
    'name': '0',
    'floorNumber': 0,
    'point': {
      'x': 30.442092286177164,
      'y': 1,
      'z': -5.988729826214325
    }
  }, {
    'name': '0',
    'floorNumber': 0,
    'point': {
      'x': 25.10135012701729,
      'y': 1,
      'z': 39.06534862281782
    }
  }, {
    'name': '0',
    'floorNumber': 0,
    'point': {
      'x': 33.568529867378516,
      'y': 1,
      'z': 30.646163890076195
    }
  }, {
    'name': '1',
    'floorNumber': 1,
    'point': {
      'x': 21.862205763706953,
      'y': 1,
      'z': 43.54129187011722
    }
  }, {
    'name': '1',
    'floorNumber': 1,
    'point': {
      'x': 0.9603323313979146,
      'y': 1,
      'z': 48.7016536008484
    }
  }, {
    'name': '1',
    'floorNumber': 1,
    'point': {
      'x': 0.5207947031863966,
      'y': 1,
      'z': 1.179041983822117
    }
  }, {
    'name': '2',
    'floorNumber': 2,
    'point': {
      'x': -19.24502268558758,
      'y': 1,
      'z': 35.21106715891918
    }
  }, {
    'name': '2',
    'floorNumber': 2,
    'point': {
      'x': 22.347041727669136,
      'y': 1,
      'z': 51.55862585449218
    }
  }, {
    'name': '2',
    'floorNumber': 2,
    'point': {
      'x': 45.83005636359384,
      'y': 1,
      'z': 30.507236583340955
    }
  }, {
    'name': '2',
    'floorNumber': 2,
    'point': {
      'x': 44.40977488890209,
      'y': 1,
      'z': 38.22366215052756
    }
  }, {
    'name': '2',
    'floorNumber': 2,
    'point': {
      'x': 34.343675210192245,
      'y': 1,
      'z': 39.143950237239096
    }
  }, {
    'name': '3',
    'floorNumber': 3,
    'point': {
      'x': -41.70370930828225,
      'y': 1,
      'z': 33.7295105287823
    }
  }, {
    'name': '3',
    'floorNumber': 3,
    'point': {
      'x': -48.50065297950898,
      'y': 1,
      'z': 31.520644731963785
    }
  }, {
    'name': '3',
    'floorNumber': 3,
    'point': {
      'x': -31.941464152505766,
      'y': 1,
      'z': 36.220968370407405
    }
  }],
  // 单层楼线数据
  lines: [{
    'name': '0',
    'floorNumber': 0,
    'points': [[56.38492850271006, 1, -47.89372069981417], [3.694515668706096, 1, 26.266998737642325], [-66.64355436603799, 1, -25.805319943338617]],
    'object': null
  }, {
    'name': '1',
    'floorNumber': 1,
    'points': [[62.764280804993376, 1, -28.682749590368502], [37.70442371001562, 1, 56.79135290527347], [13.725774627677907, 1, 24.091310180664067], [-14.879548649931657, 1, 17.609270368936876], [-14.060337530455378, 1, 34.79135290527347], [-13.963718696602633, 1, 34.79135290527344]],
    'object': null
  }, {
    'name': '2',
    'floorNumber': 2,
    'points': [[-9.073790201109041, 1, -8.14015671306501], [-27.770881177917524, 1, 17.367222779455517], [-4.881545814909103, 1, 39.15863195800782], [37.98604989903403, 1, 22.058625854492192], [38.00138653037596, 1, 22.05862585449222]],
    'object': null
  }],
  // 单层楼面数据
  faces: [{
    'name': '0',
    'floorNumber': 0,
    'points': [[48.19543693664178, 1, 25.524091072088993], [43.42621255948951, 1, 5.478211594660564], [9.343681417964895, 1, 29.52017499366795], [-14.563422550139215, 1, 40.6586441503631], [-14.563422550139215, 1, 40.6586441503631]],
    'object': null
  }, {
    'name': '1',
    'floorNumber': 1,
    'points': [[3.2562639370668762, 1, -31.755361027976875], [-45.79662199505052, 1, 43.54135290527344], [54.59824461562726, 1, 34.25374574936322], [54.59824461562726, 1, 34.25374574936322]],
    'object': null
  }, {
    'name': '2',
    'floorNumber': 2,
    'points': [[-63.14126860012775, 1, 3.847754136263376], [-40.379392635945614, 1, 31.096754418996113], [9.648094166180634, 1, 38.20272745012694], [54.41716611130166, 1, 30.037158720386657], [54.15405120269154, 1, 30.037154782530877]],
    'object': null
  }, {
    'name': '3',
    'floorNumber': 3,
    'points': [[-59.976867803047874, 1, 0.6244902557722014], [-50.840403093698406, 1, 22.758265451262986], [-30.50407068969907, 1, 44.417158903797244], [-19.9458444844556, 1, 33.366194964437724], [61.246426804556904, 1, 37.611604504348165], [61.24642680455203, 1, 37.611604504348165]],
    'object': null
  }]

};

// 跨层楼层点、线、面的数据
let floorsParams = window.floorsParams = {
  // 跨层楼点数据
  points: [{
    name: '',
    points: [{
      name: '',
      floorNumber: 0,
      point: new THREE.Vector3()
    }]
  }],
  // 跨层楼线数据
  lines: [{
    name: '',
    points: [{
      name: '',
      floorName: 0,
      point: new THREE.Vector3()
    }]
  }],
  // 跨层区域数据
  box: [{
    name: '',
    startFloorNumber: 0,
    endFloorNumber: 1,
    points: [new THREE.Vector3()]
  }]
};

// 初始化场景
function initCSR() {
  const w = canvas.offsetWidth;
  const h = canvas.offsetHeight;

  camera = new THREE.PerspectiveCamera(75, w / h, 0.1, 10000);
  camera.position.set(0, 60, 100);

  window.scene = scene = new THREE.Scene();
  // scene.background = new THREE.Color(0xefefef);
  // scene.fog = new THREE.Fog( 0xefefef, 100, 500 );

  renderer = new THREE.WebGLRenderer({
    canvas,
    antialias: true,
    alpha: true,
    premultipliedAlpha: true
  });
  renderer.outputEncoding = THREE.sRGBEncoding;
  renderer.sortObjects = false;
  camera.updateProjectionMatrix();
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(w, h, false);
}

// 初始化灯光
function initLight() {
  const ambientLight = new THREE.AmbientLight(0xFFFFFF, .6);
  scene.add(ambientLight);

  const directionalLight = new THREE.DirectionalLight(0xFFFFFF, 1);
  directionalLight.position.set(-1000, 1000, -1000);
  scene.add(directionalLight);
}

// 初始化模型
function initModel() {
  const gltfLoader = new GLTFLoader();
  // Optional: Provide a DRACOLoader instance to decode compressed mesh data
  const dracoLoader = new DRACOLoader();
  dracoLoader.setDecoderPath('/static/examples/js/libs/draco/');
  gltfLoader.setDRACOLoader(dracoLoader);
  let textureLoader = new THREE.TextureLoader();
  const texture = textureLoader.load(baseUrl + 'static/images/floor.jpeg');
  gltfLoader.load(baseUrl + 'static/models/666.glb', onLoad, onProgress, onError);


  function onLoad(gltf) {
    const gltfScene = gltf.scene;
    // gltfScene.traverse((object) => {
    //   if(object.isMesh) {
    //     // object.material.transparent = false;
    //     // object.material.opacity = 1;
    //     if(object.material.transparent) {
    //       object.material = new THREE.MeshBasicMaterial({
    //         color: object.material.color,
    //         map: texture,
    //         transparent: true,
    //         opacity: object.material.opacity
    //       });
    //     } else {
    //       const meshBasicMaterial = new THREE.MeshBasicMaterial();
    //       meshBasicMaterial.copy(object.material)
    //       object.material = new THREE.MeshBasicMaterial({ ...meshBasicMaterial });
    //     }
    //   }
    // });
    gltfScene.children.forEach(value => {

      buildingParams[value.name] = {
        floorNumber: 0,
        floorH: 6,
        position: new THREE.Vector3(),
        object: value.clone(),
        // object: mesh.clone(),
        userData: value.userData
      };
      buildingGroup.add(buildingParams[value.name].object);
      buildingGroup.name = 'buildingGroup';
    });

    // 名对象名字处理一下
    Object.values(buildingParams)
      .forEach(value => {
        value.object.traverse(object => {
          if(object.type === 'Mesh') {
            const {
              map,
              color,
              transparent,
              opacity,
            } = object.material;
            object.material = new THREE.MeshBasicMaterial({
              color,
              map,
              transparent,
              opacity,
              side: THREE.DoubleSide
            });
            // 	object.material = new THREE.MeshPhongMaterial({color, map, transparent, opacity, side: THREE.DoubleSide})
            // 	object.material = new THREE.MeshLambertMaterial({color, map, transparent, opacity, side: THREE.DoubleSide})
          }
          if(object.name !== 'lines' && object.name !== 'floorLineGroup' && object.name !== 'floorFaceGroup') {
            object.name = value.object.name;
          }
        });
      });

    // 添加到射线识别的组
    raycasterObject.push(...buildingGroup.children);
    scene.add(buildingGroup);

    if(guiParams.open) {
      setTimeout(() => openOrCloseFloor(true), 0);
    }
  }

  // scene.add(new THREE.AxesHelper(100))

  function onProgress(xhr) {
    // console.log(xhr)
  }

  function onError(err) {
    console.error(err);
  }
}

// 设置模型居中
function setModelCenter(model) {
  model.updateWorldMatrix();
  const box = new THREE.Box3().setFromObject(model);
  const boxSize = box.getSize();
  const center = box.getCenter(new THREE.Vector3());
  model.translateY(-center.y);
  model.translateX(-center.x);
  model.translateZ(-center.z);
  model.position.copy(center);
  if(boxSize.x > boxSize.y) {
    camera.position.z = boxSize.x * -1;
  } else {
    camera.position.z = boxSize.y * -1;
  }
  camera.lookAt(0, 0, 0);
}

// 初始化控制器
function initControls() {
  {
    orbitControls = new OrbitControls(camera, canvas);
    orbitControls.enableDamping = true;
    orbitControls.screenSpacePanning = true;
    orbitControls.enableKeys = false;
    orbitControls.mouseButtons = {
      LEFT: THREE.MOUSE.PAN,
      MIDDLE: THREE.MOUSE.DOLLY,
      RIGHT: THREE.MOUSE.ROTATE
    };
    window.orbitControls = orbitControls;
  }
  // orbitControls.enabled = false

  {
    // flyControls = new FlyControls(camera, canvas);
    // flyControls.movementSpeed = 100
    // flyControls.rollSpeed = 1
    // flyControls.dragToLook = true
  }

  // setTimeout(() => {
  // 	orbitControls.dispose()
  // 	orbitControls = new OrbitControls(camera, canvas);
  // }, 2000)
  // orbitControls.target.set(0, 0, 0)
}

// 初始化帮手
function initHelper() {
  stats = new Stats();
  body.appendChild(stats.domElement);

  const gui = new GUI();

  gui.add(guiParams, 'open')
    .onChange((boolean) => {
      openOrCloseFloor(boolean);
    })
    .listen();

  mousePoint = drawPoint(scene, new THREE.Vector3());

  gui.add(guiParams, 'drawPoint')
    .onChange((boolean) => {
      if(boolean) mousePoint.material.color = new THREE.Color(0xFF0000);
    })
    .listen();
  gui.add(guiParams, 'drawLine')
    .onChange((boolean) => {
      if(boolean) {
        pointsList = []; // 清空

        const objectByName = buildingGroup.getObjectByName(guiParams.selectFloorActive);
        // 线信息处理
        line = new THREE.Group();
        line.name = 'line';
        lineGroup = objectByName.getObjectByName('floorLineGroup');
        if(!lineGroup) { // 如果保存这些线的组不存在则创建
          lineGroup = new THREE.Group();
          lineGroup.name = 'floorLineGroup';
          objectByName.add(lineGroup);
        }

        mousePoint.material.color = new THREE.Color(0xFFFF00);
      } else {
        lineGroup = null;
      }
    })
    .listen();
  gui.add(guiParams, 'drawFace')
    .onChange((boolean) => {
      if(boolean) {
        pointsList = [];

        const objectByName = buildingGroup.getObjectByName(guiParams.selectFloorActive);
        // 面信息处理
        face = new THREE.Group();
        face.name = 'face';
        faceGroup = objectByName.getObjectByName('floorFaceGroup');
        if(!faceGroup) { // 如果保存这些线的组不存在则创建
          faceGroup = new THREE.Group();
          faceGroup.name = 'floorLineGroup';
          objectByName.add(faceGroup);
        }

        mousePoint.material.color = new THREE.Color(0x0000FF);
      } else {
        faceGroup = null;
      }
    })
    .listen();

  gui.add(guiParams, 'selectFloorActive')
    .options(guiParams.selectFloor)
    .onChange(number => {
      console.log(number);
      guiParams.selectFloorActive = number;

      if(+number !== -1) {
        focusFloor(number);
      } else {
        // buildingGroup.children.forEach(value => {
        // 	raycasterObject.push(value)
        // })
      }

      const objectByName = buildingGroup.getObjectByName(guiParams.selectFloorActive);
      pointsList = [];
      // 线信息处理
      line = new THREE.Group();
      line.name = 'line';
      lineGroup = objectByName.getObjectByName('floorLineGroup');
      if(!lineGroup) { // 如果保存这些线的组不存在则创建
        lineGroup = new THREE.Group();
        lineGroup.name = 'floorLineGroup';
        objectByName.add(lineGroup);
      }
      // 面信息处理
      face = new THREE.Group();
      face.name = 'face';
      faceGroup = objectByName.getObjectByName('floorFaceGroup');
      if(!faceGroup) { // 如果保存这些线的组不存在则创建
        faceGroup = new THREE.Group();
        faceGroup.name = 'floorLineGroup';
        objectByName.add(faceGroup);
      }
    })
    .listen();
}

// 展开合并楼层
function openOrCloseFloor(boolean) {
  buildingGroup.children.forEach((value, index) => {
    new TWEEN.Tween({ position: value.position.y }).to({
      position: boolean ? value.position.y + value.name * 30 :
        value.position.y - value.name * 30
    }, 500)
      .onUpdate(val => {
        value.position.setY(val.position);
      })
      .onComplete(value => {
        console.log(buildingGroup.children[index].name);
        console.log(buildingGroup.children[index].name * 12);
      })
      .start();
  });
}

// 响应式控制窗口大小
function onWindowResize() {
  renderer.setPixelRatio(window.devicePixelRatio);
  const width = canvas.offsetWidth;
  const height = canvas.offsetHeight;
  camera.aspect = width / height;
  camera.updateProjectionMatrix();
  renderer.setSize(width, height, false);
}

// 渲染
function render() {
  if(orbitControls) orbitControls.update();
  if(flyControls) flyControls.update(clock.getDelta());
  if(TWEEN) TWEEN.update();
  renderer.render(scene, camera);
  if(stats) stats.update();
}

// 循环渲染
function animation() {
  requestAnimationFrame(animation);
  render();
}

// 添加监听器
function addEL() {
  window.addEventListener('resize', onWindowResize);
  canvas.addEventListener('pointerdown', mouseDown, false);
  canvas.addEventListener('pointermove', mouseMove, false);
  canvas.addEventListener('pointerup', mouseUp, false);
  canvas.addEventListener('dblclick', ev => {
    console.log(ev);
  }, false);
  canvas.onmouseup = function(ev) {
    console.log(JSON.stringify(pointsList));
    if(ev.button === 2) {
      if(guiParams.drawLine) {
        floorParams.lines.push({
          name: guiParams.selectFloorActive,
          floorNumber: +guiParams.selectFloorActive,
          points: pointsList,
          object: null
        });
      }
      if(guiParams.drawFace) {
        floorParams.faces.push({
          name: guiParams.selectFloorActive,
          floorNumber: +guiParams.selectFloorActive,
          points: pointsList,
          object: null
        });
      }

      // guiParams.selectFloorActive = -1
      guiParams.drawPoint = false;
      guiParams.drawLine = false;
      guiParams.drawFace = false;
    }
  };
}

// 按下
function mouseDown(e) {
  //
  mouse.x = (e.offsetX / canvas.offsetWidth) * 2 - 1;
  mouse.y = -(e.offsetY / canvas.offsetHeight) * 2 + 1;
  //
  raycaster.setFromCamera(mouse, camera);
  let intersectObjects = raycaster.intersectObjects(raycasterObject, true);
  console.log(intersectObjects);
  // 有拾取到东西
  if(intersectObjects.length) {
    const object = intersectObjects[0];
    // 保存鼠标按下的点位置-----为单击操作使用
    mouseClick.copy(mouse);

    // 画线的第一个点
    if(guiParams.drawLine || guiParams.drawFace) {
      console.log(pointsList);
      if(guiParams.selectFloorActive === object.object.name) {
        if(pointsList.length < 1) {
          pointsList = [];
          pointsList.push([object.point.x, 1, object.point.z]);
          pointsList.push([object.point.x, 1, object.point.z]);
        } else {
          pointsList.push([object.point.x, 1, object.point.z]);
        }
      }
    }
  }
}

// 移动
function mouseMove(e) {
  //
  mouse.x = (e.offsetX / canvas.offsetWidth) * 2 - 1;
  mouse.y = -(e.offsetY / canvas.offsetHeight) * 2 + 1;
  //
  raycaster.setFromCamera(mouse, camera);
  let intersectObjects = raycaster.intersectObjects(raycasterObject, true);

  // 有拾取到东西
  if(intersectObjects.length) {
    const object = intersectObjects[0];
    // 鼠标移动高亮
    hoverFloor(object.object.name);

    // 需要 让点 跟随鼠标
    if(guiParams.drawPoint || guiParams.drawLine || guiParams.drawFace) {
      if(mousePoint) {
        mousePoint.visible = true;
        mousePoint.position.copy(object.point);
      } else {
        mousePoint = drawPoint(scene, new THREE.Vector3());
      }
    }

    // 画线
    if(guiParams.drawLine) {
      pointsList.pop();
      pointsList.push([object.point.x, 1, object.point.z]);
      lineGroup.remove(line);
      line = drawLine(lineGroup, pointsList);
    }

    // 画面
    if(guiParams.drawFace) {
      pointsList.pop();
      pointsList.push([object.point.x, 1, object.point.z]);
      faceGroup.remove(face);
      // face = drawFace(faceGroup, pointsList);
      face = drawConcaveFace(faceGroup, pointsList);
    }

  } else {
    // 鼠标移动高亮
    hoverFloor(-1);

    // 隐藏跟随鼠标的点
    if(mousePoint) mousePoint.visible = false;
  }
}

// 弹起
function mouseUp(e) {
  //
  mouse.x = (e.offsetX / canvas.offsetWidth) * 2 - 1;
  mouse.y = -(e.offsetY / canvas.offsetHeight) * 2 + 1;
  //
  raycaster.setFromCamera(mouse, camera);
  let intersectObjects = raycaster.intersectObjects(raycasterObject, true);

  // 有拾取到东西
  if(intersectObjects.length) {
    const object = intersectObjects[0];
    // 单击了同一个位置
    if(mouseClick.equals(mouse)) {
      // 设置焦点
      guiParams.selectFloorActive = object.object.name; // active状态的楼层
      focusFloor(object.object.name);

      // 标点 guiParams.drawPoint 是否开启标点
      if(guiParams.drawPoint) {
        const currentlyClickedFloor = buildingGroup.getObjectByName(guiParams.selectFloorActive);
        let points = currentlyClickedFloor.getObjectByName('points');
        if(!points) {
          points = new THREE.Group();
          points.name = 'points';
          currentlyClickedFloor.add(points);
        }
        drawPoint(points, new THREE.Vector3().copy(object.point.setY(0)));

        floorParams.points.push({
          name: guiParams.selectFloorActive,
          floorNumber: +guiParams.selectFloorActive,
          point: new THREE.Vector3().copy(object.point.setY(1)),
          // object: Object.values(buildingParams).filter(value => +value.object.name === +guiParams.selectFloorActive)[0] || null
        });
      }
    }
  }
}

// 启动
(function() {
  initCSR();
  initLight();
  initHelper();
  initModel();
  initControls();
  addEL();
  // setTimeout(() => render(), 100)
  animation();
})();

/**
 * 画点
 * @param pointGroup
 * @param point
 * @param options
 * @returns {Points}
 */
function drawPoint(pointGroup, point, options) {
  const {
    color,
    transparent,
    opacity,
    side,
    depthTest,
    isLine
  } = options || {};
  const material = new THREE.PointsMaterial({
    color: color || 0xFF0000,
    transparent: transparent || true,
    opacity: opacity || 1,
    side: side || THREE.FrontSide,
    depthTest: depthTest || true
  });
  //设置具有几何顶点的几何（Geometry）或缓冲区几何（BufferGeometry）设置顶点位置，看名字就知道了，一个是直接将数据保存在js里面的，另一个是保存在WebGL缓冲区内的，而且肯定保存到WebGL缓冲区内的效率更高
  const geometry = new THREE.Geometry();
  geometry.vertices.push(point);
  //使用Line方法将线初始化
  const p = new THREE.Points(geometry, material);
  p.name = 'point';
  pointGroup.add(p);
  return p;
}

/**
 * 画线
 * @param lineGroup 线添加到指定的组或者Object3D
 * @param pointList 线的点
 * @param options {color, transparent, opacity, side, depthTest, isLine}
 * @returns {Mesh} 线
 */
function drawLine(lineGroup, pointList, options) {
  const {
    color,
    transparent,
    opacity,
    side,
    depthTest,
    isLine
  } = options || {};
  const material = new THREE.LineBasicMaterial({
    color: color || 0xffFF00,
    transparent: transparent || true,
    opacity: opacity || 1,
    side: side || THREE.FrontSide,
    depthTest: depthTest || true
  });
  //设置具有几何顶点的几何（Geometry）或缓冲区几何（BufferGeometry）设置顶点位置，看名字就知道了，一个是直接将数据保存在js里面的，另一个是保存在WebGL缓冲区内的，而且肯定保存到WebGL缓冲区内的效率更高
  const geometry = new THREE.Geometry();
  pointList.forEach(value => {
    geometry.vertices.push(new THREE.Vector3(...value));
  });
  //使用Line方法将线初始化
  const line = new THREE[!isLine ? 'LineLoop' : 'Line'](geometry, material);
  line.name = 'line';
  lineGroup.add(line);
  return line;
}

/**
 * 画面
 * @param faceGroup 面添加到指定的组或者Object3D
 * @param pointList 面的点
 * @param options {color, transparent, opacity, side, depthTest}
 * @returns {Mesh} 面
 */
function drawFace(faceGroup, pointList, options) {
  const {
    color,
    transparent,
    opacity,
    side,
    depthTest
  } = options || {};
  const geometry = new THREE.Geometry();

  pointList.forEach(points => {
    geometry.vertices.push(new THREE.Vector3(...points));
  });
  const vector3 = new THREE.Vector3();
  const c = new THREE.Color(0xffffff);
  for(let i = 2; i < pointList.length; i++) geometry.faces.push(new THREE.Face3(0, i - 1, i, vector3, c, i));

  const material = new THREE.MeshBasicMaterial({
    color: color || 0xff0000,
    transparent: transparent || true,
    opacity: opacity || 1,
    side: side || THREE.FrontSide,
    depthTest: depthTest || true
  });
  face = new THREE.Mesh(geometry, material);
  face.name = 'face';
  faceGroup.add(face);
  return face;
}

function drawConcaveFace(faceGroup, pointList, options) {
  const {
    color,
    transparent,
    opacity,
    side,
    depthTest
  } = options || {};
  // 用来创建凹包多边形的点,一定要按顺序哦
  let points = pointList || [[-54.51656453437723, 1, 1.2589797085067005], [77.55965243483786, 1, -2.7014522917014316], [50.4712618179327, 1, 39.831863993281885], [61.294966872171635, 1, 17.906923970755788], [41.42827914953114, 1, 40.43287140358973], [52.46129981923488, 1, 25.300708035104805], [35.480088997645694, 1, 41.21410334221805], [45.91584726363737, 1, 3.147038614363776], [23.1326431353664, 1, 44.14930098879374], [14.715727847219249, 1, 4.227067838395428], [4.139243097593116, 1, 42.74382135933986], [-11.22812356725084, 1, 4.42859759204563], [-13.299133799029057, 1, 44.40443733941794], [-29.746566875327552, 1, 6.471678581871359], [-37.38846104792808, 1, 40.186931347900696], [-54.31886840085025, 1, 7.701349574558144], [-54.31886840085025, 1, 7.701349574558144]];
  let list = [];// 用来装点位的数组

  // 将目标数组改成Vector2 这里默认去掉高度y,当然如果你喜欢可以用其他轴的
  for(let i = 0; i < points.length; i++) list.push(new THREE.Vector2(points[i][0], points[i][2]));

  // 用这些点位生成一个 Geometry
  let geometry = new THREE.ShapeGeometry(new THREE.Shape(list));

  const material = new THREE.MeshBasicMaterial({
    color: color || 0xff0000,
    transparent: transparent || true,
    opacity: opacity || .5,
    side: side || THREE.BackSide,
    depthTest: depthTest || false
  });

  // 这就是你要的多边形啦
  let face = new THREE.Mesh(geometry, material);
  face.name = 'face';
  face.add(new THREE.AxesHelper());
  face.rotateX(Math.PI / 2);
  faceGroup.add(face);
  face.position.setY(1);
  return face;
}

drawConcaveFace(faceGroup);

// 聚焦 楼层
function focusFloor(number) {
  hoverFloor(number);
}

// hover 楼层
function hoverFloor(number) {
  // Object.values(buildingParams).forEach((value, index) => {
  // 	if (number === value.object.name || guiParams.selectFloorActive === value.object.name) {
  // 		value.object.traverse(object => {
  // 			if (object.type === 'Mesh') {
  // 				if (object.name !== 'point' && object.name !== 'line' && object.name !== 'face') {
  // 					object.material.transparent = true
  // 					object.material.opacity = 1
  // 				}
  // 			}
  // 		})
  // 	} else {
  // 		value.object.traverse(object => {
  // 			if (object.type === 'Mesh') {
  // 				if (object.name !== 'point' && object.name !== 'line' && object.name !== 'face') {
  // 					object.material.transparent = true
  // 					object.material.opacity = .8
  // 				}
  // 			}
  // 		})
  // 	}
  // })
}

// 获取并设置点
function getAndSetPoints() {
  floorParams.points.forEach(value => {
    const buildingParam = buildingParams[value.name];
    if(buildingParam.object.getObjectByName('points')) {
      const points = new THREE.Group();
      points.name = 'points';
    }
    drawPoint(buildingParam.object, new THREE.Vector3(...Object.values(value.point)));
  });
}

// 获取并设置线
function getAndSetLine() {
  floorParams.lines.forEach(value => {
    const buildingParam = buildingParams[value.name];
    if(buildingParam.object.getObjectByName('floorLineGroup')) {
      const floorLineGroup = new THREE.Group();
      floorLineGroup.name = 'floorLineGroup';
    }
    drawLine(buildingParam.object, value.points);
  });
}

// 获取并设置面
function getAndSetFace() {
  floorParams.faces.forEach(value => {
    const buildingParam = buildingParams[value.name];
    if(buildingParam.object.getObjectByName('floorFaceGroup')) {
      const floorLineGroup = new THREE.Group();
      floorLineGroup.name = 'floorFaceGroup';
    }
    drawLine(buildingParam.object, value.points, { isLine: true });
    drawConcaveFace(buildingParam.object, value.points);
  });
}

const interval = setInterval(() => {
  if(buildingGroup.getObjectByName('2')) {
    getAndSetPoints();
    getAndSetLine();
    getAndSetFace();
    clearInterval(interval);
  }
}, 800);

// setTimeout(() => {
//
// 	// Instantiate a exporter
// 	const gltfExporter = new GLTFExporter();
//
// 	function exportGLTF(input) {
//
// 		gltfExporter.parse(input, function (result) {
//
// 			if (result instanceof ArrayBuffer) {
// 				saveArrayBuffer(result, 'scene.glb');
// 			} else {
// 				const output = JSON.stringify(result, null, 2);
// 				console.log(output);
// 				saveString(output, 'scene.gltf');
// 			}
// 		}, {binary: true});
// 	}
//
// 	function saveString(text, filename) {
// 		save(new Blob([text], {type: 'text/plain'}), filename);
// 	}
//
// 	function saveArrayBuffer(buffer, filename) {
// 		save(new Blob([buffer], {type: 'application/octet-stream'}), filename);
// 	}
//
// 	function save(blob, filename) {
// 		link.href = URL.createObjectURL(blob);
// 		link.download = filename;
// 		link.click();
// 		// URL.revokeObjectURL( url ); breaks Firefox...
// 	}
//
// 	const link = document.createElement('a');
// 	link.style.display = 'none';
// 	document.body.appendChild(link); // Firefox workaround, see #6594
//
// 	for (let key in buildingParams) {
// 		let meshArr = [];
// 		let materialArr = [];
// 		buildingParams[key].object.rotateX(-90)
// 		console.log(buildingParams[key].object)
// 		buildingParams[key].object.traverse(function (child) {
// 			if (child.isMesh) {
// 				meshArr.push(child);
// 				materialArr.push(child.material);
// 			}
// 		});
//
// 		let geometry = new THREE.Geometry();
// 		for (let i = 0; i < meshArr.length; i++) {
// 			meshArr[i].updateMatrix();
// 			let geo = new THREE.Geometry();
// 			if (meshArr[i].geometry.type === "Geometry"){
// 				geo = meshArr[i].geometry
// 			} else {
// 				geo.fromBufferGeometry(meshArr[i].geometry)
// 			}
// 			geometry.merge(geo, meshArr[i].matrix, i)
// 			// geometry.merge(new THREE.Geometry().fromBufferGeometry(meshArr[i].geometry), meshArr[i].matrix, i);
// 		}
//
// 		let mesh = new THREE.Mesh(geometry, materialArr);
// 		mesh.scale.set(0.001, 0.001, 0.001)
//
// 		// mesh.rotateX(60)
// 		console.log(mesh)
// 		scene.add(mesh)
// 		// exportGLTF(mesh)
// 	}
//
//
// }, 800)
